using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using App_Code.Conexao;


namespace App_Code.Interface
{
    public abstract class BdAbstrato<T> where T : class
    {
        private SqlCommand _command;
        private SqlConnection _conn;
        private SqlDataAdapter _dataAdapter;

        protected BdAbstrato(ConfiguradorConexao configuradorConexao)
        {
            Configurador = configuradorConexao;
        }
        protected ConfiguradorConexao Configurador { get; set; }
        private bool UsarMultiResultSet { get; set; }
        protected T ObjetoCorrente { get; set; }


        protected string UrlBd
        {
            get
            {
                return _conn.ConnectionString;
            }
        }

        protected void ComandoSql(string sql, CommandType commandType)
        {
            _conn = Configurador.Conn;
            _command = _conn.CreateCommand();
            _command.CommandText = sql;

            if(commandType == CommandType.StoredProcedure)
            {
                _command.CommandType = CommandType.StoredProcedure;
            }
        }

        public virtual void Adicionar(T t)
        {
            throw new NotImplementedException();
        }

        public virtual void Atualizar(T t)
        {
            throw new NotImplementedException();
        }

        public virtual void Excluir(T t)
        {
            throw new NotImplementedException();
        }

        public virtual T Consultar(T t)
        {
            throw new NotImplementedException();
        }

        public virtual List<T> Listar(T t)
        {
            throw new NotImplementedException();
        }

        protected virtual void PreencherObjeto(ref T t, IDataReader reader)
        {
            throw new NotImplementedException();
        }

        protected List<T> MontarListagem()
        {
            var resultado = new List<T>();
            IDataReader dataReader = null;
            T corrente = null;

            try
            {
                if(_conn != null)
                {
                    if(_conn.State == ConnectionState.Closed)
                    {
                        _conn.Open();
                    }
                    dataReader = _command.ExecuteReader();

                    if(dataReader != null)
                    {
                        while(dataReader.Read())
                        {
                            var t = (T) Activator.CreateInstance(typeof (T));
                            PreencherObjeto(ref t, dataReader);

                            if(t != corrente )
                            {
                                resultado.Add(t);
                                corrente = t;
                            }
                            
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                GereciadorErro(ex);
            }
            finally
            {
                if(dataReader != null && !dataReader.IsClosed)
                {
                    dataReader.Close();
                }
                if(!UsarMultiResultSet && (_conn != null && _command.Transaction == null))
                {
                    _conn.Close();
                }
            }

            return resultado;
        }

        protected T MontarObjeto()
        {
            IDataReader dataReader = null;
            T t = default(T);
            try
            {
                if (_conn != null)
                {
                    if (_conn.State == ConnectionState.Closed)
                    {
                        _conn.Open();
                    }

                    dataReader = _command.ExecuteReader();

                    if (dataReader != null)
                    {
                        if (dataReader.Read())
                        {
                            t = (T)Activator.CreateInstance(typeof(T));
                            PreencherObjeto(ref t, dataReader);
                        }
                    }
                }
            }
            catch (SqlException ex)
            {
                GereciadorErro(ex);
            }
            finally
            {
                if (dataReader != null && !dataReader.IsClosed)
                {
                    dataReader.Close();
                }

                if (!UsarMultiResultSet && (_conn != null && _command.Transaction == null))
                {
                    _conn.Close();
                }
            }

            return t;
        }

        protected bool ExecutarComando()
        {
            bool resultado = false;

            try
            {
                if (_command != null)
                {
                    if (_command.Connection != null)
                    {
                        if (_command.Connection.State == ConnectionState.Closed)
                        {
                            _command.Connection.Open();
                        }

                        int linhasAfetadas = _command.ExecuteNonQuery();
                        resultado = (linhasAfetadas > 0);
                    }
                }
            }
            catch (SqlException ex)
            {
                GereciadorErro(ex);
            }
            finally
            {
                if (!UsarMultiResultSet && (_conn != null && (_command != null && _command.Transaction == null)))
                {
                    _conn.Close();
                }
            }

            return resultado;
        }

        protected void AdicionarParametro(string name, object value)
        {
            if (_command != null)
            {
                if (value != null)
                {
                    if (value is DateTime)
                    {
                        var parameter = new SqlParameter(name, SqlDbType.DateTime);
                        parameter.Value = value;
                        _command.Parameters.Add(parameter);
                    }
                    else
                    {
                        _command.Parameters.Add(new SqlParameter(name, value));
                    }
                }
                else
                {
                    _command.Parameters.Add(new SqlParameter(name, DBNull.Value));
                }
            }
        }

        protected void AdicionarParametroNulo<U>(string name, U value)
        {
            if (_command != null)
            {
                if (Equals(value, default(U)))
                {
                    _command.Parameters.Add(new SqlParameter(name, DBNull.Value));
                }
                else
                {
                    _command.Parameters.Add(
                        new SqlParameter(name, value));
                }
            }
        }

        public void GereciadorErro(Exception ex)
        {
            if(_conn != null)
            {
                if(_command.Transaction != null && _command.Connection.State == ConnectionState.Open)
                {
                    _command.Transaction.Rollback();
                }
            }
        }

    }

    
}